//声明构造函数
function Promise(executor){
    this.PromiseState='pending'; //默认初始化时就是pending状态
    this.PromiseResult=null;  //返回的内容
    this.callbacks=[];
    const self=this;

        /**
     * 函数中的this指向取决于函数的调用者，也就是说谁调用了这个函数，那么函数中的this就指向谁
     * 函数中this不光可以得到另一个函数中的this指向，还可以直接修改成想要的this指向
     * 修改函数中的this指向三种：call、apply、bind
     * call和apply之间的区别：在于函数中修改完this指向，实际参数传递的格式不同
     * 语法：
     * 函数名.call(新的this指向,实际参数1,实际参数2....)
     * 函数名.apply(新的this指向,[实际参数1,实际参数2....])
     * call和apply之间的共同点：在于函数一旦修改完想要的this指向之后，则函数就会立即执行
     * call和bind之前的区别：call会立即执行，bind不会立即执行，且bind只有返回值，
     * 且返回的是与原函数结构一模一样的修改完this指向的新函数
     */

    function resolve (val){
        if(self.PromiseState !=='pending') return;
        self.PromiseState='fulfilled';
        self.PromiseResult=val;
        self.callbacks.forEach(element => {
            element.onFulfilled();
        });
    }

    //箭头函数中的定义，如果形式参数只有一个，那么是可以省略小括号的
    const reject= val=>{
        if(this.PromiseState !=='pending') return;
        this.PromiseState='rejected';
        this.PromiseResult=val;
        this.callbacks.forEach(element => {
            element.onRejected();
        });
    }
    try{
        executor(resolve,reject);
    }catch(ex) {
        reject(ex);
    }
}

//then 方法
Promise.prototype.then= function(onResolved, onRejected){
    const self= this;
    if(!(onResolved instanceof Function)){ onResolved= val =>val;}
    if(!(onRejected instanceof Function)){onRejected= reason=> {throw reason}}       
    return new Promise((resolve,reject)=>{
        //封装函数
        function myCallback(typeMethod){
            setTimeout(() => {
                try{
                    let result= typeMethod (self.PromiseResult);
                    if(result instanceof Promise){
                        result.then(v=>{ resolve(v)},r=>{ reject(r)})
                    }else{
                        resolve(result);
                    }
                }catch(ex){
                    reject(ex);
                }
            });
        }
        if(this.PromiseState==='fulfilled'){
           myCallback(onResolved);

        }else if(this.PromiseState==='rejected'){
            myCallback(onRejected);
        }else{ //状态为 pending
            this.callbacks.push({
                onFulfilled:function(){
                    myCallback(onResolved);
                },
                onRejected:function(){
                    myCallback(onRejected); 
                }
            })
        }


    })
}

// catch方法
Promise.prototype.catch=function(onRejected){
    return this.then(undefined,onRejected);
}

//resolve方法,属于该对象的方法，而不是实例的方法
Promise.resolve=function(val){
    return new Promise((resolve,reject)=>{
        if(val instanceof Promise){
            val.then(v=>{ resolve(v)},r=>{reject(r)})
        }else{
            resolve(val);
        }
    })
}

//reject
Promise.reject=function(val){
    return new Promise((resolve,reject)=>{
        reject(val);
    })
}

//all 
Promise.all=function(promises){
    return new Promise((resolve,reject)=>{
        let arr=[];
        for(let i=0; i< promises.length; i++){
            promises[i].then(v=>{
                arr[i]=v;
            },r=>{
                reject(r);
            })
        }
        resolve(arr);
    }) 
}

//race,值为第一个返回的状态
Promise.race=function(promises){
    return new Promise((resolve,reject)=>{
        for(let i=0; i< promises.length; i++){
            promises[i].then(v=>{
                resolve(v);
            },r=>{
                reject(r);
            })
        }
    });
}



//借助于Object.assign方法使用一个对象和prototype对象进行合并,相当于添加了一个then方法
// Object.assign(Promise.prototype,{
//     then(onFulfilled,onRejected){ 
//         if(!(onFulfilled instanceof Function)){ onFulfilled= val =>val;}
//         if(!(onRejected instanceof Function)){onRejected= reason=> {throw reason}}        
//         return new Promise((resolve,reject)=>{  //then 返回的是一个 promise对象
//             const _common= function(callback){
//                 setTimeout(() => {
//                     try{
//                         const value= callback(this.PromiseResult)
//                         if(value instanceof Promise){value.then(resolve,reject)
//                         }else{resolve(resultInvoke)}
//                     }catch (ex){
//                         reject(ex)
//                     }
//                 });
//             }

//             if(this.PromiseState=='fulfilled'){
//                 _common.call(this.onFulfilled);
//             }else if(this.PromiseState=='rejected'){
//                 _common.call(this.onRejected);
//             }else{
//                 this.callbacks.push({
//                     onFulfilled:_common.bind(this.onFulfilled),
//                     onRejected:_common.bind(this.onRejected)
//                 })
//             }
//         })
//     },
//     catch(onRejected){
//         return this.then(undefined,onRejected)
//     }
// })

 



